package buildrobot_info

import (
	"fmt"
	"go_server/game_server/api/service/build"
	"go_server/game_server/dao"
	"go_server/game_server/dataconfig/config_manager"
	"go_server/game_server/protocol/pb"
	"go_server/game_server/util"
	"go_server/zinx/zlog"
	"gorm.io/datatypes"
	"math"
	"strconv"
	"strings"
	"time"
)

// =========数据库表【buildrobot_info】=================================================================================
//
//	Cache_buildrobot_info
//
// ===================================================================================================================
type func_buildrobot_info_GetRobotById func(robotSerid int32) (*Cache_buildrobot_info_robot_data, bool)

type Cache_buildrobot_info struct {
	RoleId            int64                                        //角色Id
	MaxCount          int32                                        //最大机器人数量
	TransVolume       int32                                        //机器人运输量
	RobotData         map[int32]*Cache_buildrobot_info_robot_data  //机器人数据
	BuildData         map[string]*Cache_buildrobot_info_build_data //建筑数据
	BuildResourceData map[int32]map[int32][]int64                  //资源建筑机器人采集数据
}

// marshal, err := sonic.Marshal(rst.Data())
// string(marshal)

func (s *Cache_buildrobot_info) CreateNewRobot(count int) {
	maxrobotserid := s.GetMaxRobotSerId() //机器人最大服务器id
	cfgRobot := config_manager.GetTableRobotSheetRobot(1)
	for i := 0; i < count; i++ {
		maxrobotserid++
		nr := &Cache_buildrobot_info_robot_data{
			Serid:        maxrobotserid,
			Cfgid:        cfgRobot.Id,
			Power:        cfgRobot.Power,
			LastIdleTime: time.Now().UnixMilli(),
		}
		s.RobotData[nr.Serid] = nr
	}
}

func (s *Cache_buildrobot_info) GetRobotData() datatypes.JSONType[[]string] {
	rst := datatypes.NewJSONType(make([]string, 0))
	if s.RobotData != nil {
		rds := make([]string, 0)
		for _, v := range s.RobotData {
			rds = append(rds, v.GetValue())
		}
		rst = datatypes.NewJSONType(rds)
	}
	return rst
}

func (s *Cache_buildrobot_info) SetRobotData(json datatypes.JSONType[[]string]) {
	vals := json.Data()
	s.RobotData = make(map[int32]*Cache_buildrobot_info_robot_data)
	if vals != nil {
		for i := 0; i < len(vals); i++ {
			rd := &Cache_buildrobot_info_robot_data{}
			rd.SetValue(vals[i])
			s.RobotData[rd.Serid] = rd
		}
	}
}

func (s *Cache_buildrobot_info) GetBuildData() datatypes.JSONType[map[string]string] {
	rst := datatypes.NewJSONType(make(map[string]string, 0))
	if s.BuildData != nil {
		bds := make(map[string]string, 0)
		for bid, v := range s.BuildData {
			bds[bid] = v.GetValue()
		}
		rst = datatypes.NewJSONType(bds)
	}
	return rst
}

func (s *Cache_buildrobot_info) SetBuildData(json datatypes.JSONType[map[string]string]) {
	vals := json.Data()
	s.BuildData = make(map[string]*Cache_buildrobot_info_build_data)
	if vals != nil {
		for bid, val := range vals {
			bd := &Cache_buildrobot_info_build_data{}
			bd.SetBuild_info_id(bid)
			bd.SetValue(val)
			s.BuildData[bd.Build_info_id] = bd
		}
	}
}

func (s *Cache_buildrobot_info) GetMaxRobotSerId() int32 {
	maxserid := int32(0)
	if s.RobotData != nil {
		for serid, _ := range s.RobotData {
			maxserid = int32(math.Max(float64(maxserid), float64(serid)))
		}
	}
	return maxserid
}

func (s *Cache_buildrobot_info) GetRobotSerids() []int32 {
	serids := util.NewSet[int32]()
	if s.RobotData != nil {
		for id, _ := range s.RobotData {
			serids.Add(id)
		}
	}
	return serids.Elements()
}

func (s *Cache_buildrobot_info) GetRobotBySerid(serid int32) (*Cache_buildrobot_info_robot_data, bool) {
	rv, ok := s.RobotData[serid]
	return rv, ok
}

func (s *Cache_buildrobot_info) Pb_GetIdleRobot() []*pb.BuildRobotData {
	rstPbIdleRobots := make([]*pb.BuildRobotData, 0)
	if s.RobotData != nil {
		for _, rtv := range s.RobotData {
			if !rtv.IsWork {
				nr := &pb.BuildRobotData{
					Serid:        rtv.Serid,
					Cfgid:        rtv.Cfgid,
					Power:        rtv.Power,
					IsWork:       rtv.IsWork,
					LastIdleTime: rtv.LastIdleTime,
					LastWorkTime: rtv.LastWorkTime,
				}
				rstPbIdleRobots = append(rstPbIdleRobots, nr)
			}
		}
	}
	return rstPbIdleRobots
}

// 检测升级资源是否足够
func (s *Cache_buildrobot_info) CheckUpgradeEnough(build_info_id string) (pb.ErrorCodeManager, bool) {
	resEnough := true //资源是否足够
	/*if _, ok := s.BuildData[build_info_id]; ok {
		//如果存在，则不需要判定资源是否足够
	} else {
		//如果不存在，则是新升级建筑需要判定资源够不够
		bd := &Cache_buildrobot_info_build_data{}
		bd.SetBuild_info_id(build_info_id)
		blvCfgTable := config_manager.GetTableBuildSheetLevelConfig(bd.Build_info_cfgBuildId, bd.AfterLv)
		for _, v := range blvCfgTable.Consume {
			//CheckItemEnough会区别是否是货币
			resEnough = resEnough && bag.CheckItemEnough(bd.Build_info_roleId, v.Value[0], v.Value[1])
		}
	}*/

	code := pb.ErrorCodeManager_SUCCESS
	if !resEnough {
		code = pb.ErrorCodeManager_BUILDROBOTINFO_NOT_RESENOUGH
	}
	return code, resEnough
}

// ========数据库表【buildrobot_info】字段[robot_data]=================================================================================================
//
//	Cache_buildrobot_info_robot_data
//
// [机器人serid_配置表Id_体力值_是否工作中_最后空闲开始时间_最后工作开始时间]
// =================================================================================================================================================
type Cache_buildrobot_info_robot_data struct {
	Serid        int32 //服务器Id
	Cfgid        int32 //配置表Id
	Power        int32 //体力
	IsWork       bool  //是否工作中
	LastIdleTime int64 //最后空闲开始时间
	LastWorkTime int64 //最后工作开始时间
}

func (s *Cache_buildrobot_info_robot_data) SetValue(val string) {
	splitStr := strings.Split(val, "_")
	if len(splitStr) > 0 {
		for i, sv := range splitStr {
			if v, err := strconv.Atoi(sv); err == nil {
				switch i {
				case 0:
					{
						s.Serid = int32(v)
					}
				case 1:
					{
						s.Cfgid = int32(v)
					}
				case 2:
					{
						s.Power = int32(v)
					}
				case 3:
					{
						s.IsWork = v != 0
					}
				case 4:
					{
						s.LastIdleTime = int64(v)
					}
				case 5:
					{
						s.LastWorkTime = int64(v)
					}
				}
			}
		}
	}
}

func (s *Cache_buildrobot_info_robot_data) GetValue() string {
	int64IsWork := int64(0)
	if s.IsWork {
		int64IsWork = int64(1)
	}
	combinStr := strings.Join([]string{
		strconv.FormatInt(int64(s.Serid), 10),
		strconv.FormatInt(int64(s.Cfgid), 10),
		strconv.FormatInt(int64(s.Power), 10),
		strconv.FormatInt(int64IsWork, 10),
		strconv.FormatInt(s.LastIdleTime, 10),
		strconv.FormatInt(s.LastWorkTime, 10),
	}, "_")
	return combinStr
}

func (s *Cache_buildrobot_info_robot_data) To_PbData() *pb.BuildRobotData {
	return &pb.BuildRobotData{
		Serid:        s.Serid,
		Cfgid:        s.Cfgid,
		Power:        s.Power,
		IsWork:       s.IsWork,
		LastIdleTime: s.LastIdleTime,
		LastWorkTime: s.LastWorkTime,
	}
}

// 按空闲时间恢复体力
func (s *Cache_buildrobot_info_robot_data) PowerRecoverByTime(millisecond int64) {
	if millisecond > 0 {
		cfgv := config_manager.GetTableRobotSheetRobot(s.Cfgid)
		tpr := cfgv.PowerRecover
		if tpr != nil {
			recTime := time.UnixMilli(millisecond)
			recMinute := recTime.Minute()

			tpt := tpr[0] //每X分钟
			tps := tpr[1] //恢复体力值

			difm := float64(recMinute) / float64(tpt)
			difm /= float64(tps)

			pot := s.Power + int32(difm)

			if cfgv.PowerRange != nil {
				min := cfgv.PowerRange[0]
				max := cfgv.PowerRange[1]
				tmpv := math.Max(float64(pot), float64(min)) //<=min取min
				tmpv = math.Min(tmpv, float64(max))          //>=max 取max
				pot = int32(tmpv)
			}
			bfpower := s.Power

			s.Power = pot

			fmt.Printf("Robot[sid:%v,cfgid:%v] PowerRecoverByTime ==> beforePower:%v time:%v afterPower:%v 每%v分钟恢复%v体力",
				s.Serid, s.Cfgid, bfpower, recTime, pot, tpt, tps)
		}
	}
}

// 按时间消耗体力
func (s *Cache_buildrobot_info_robot_data) PowerConsumeByTime(millisecond int64) {
	if millisecond > 0 {
		cfgv := config_manager.GetTableRobotSheetRobot(s.Cfgid)
		tpr := cfgv.PowerConsume
		if tpr != nil {
			recTime := time.UnixMilli(millisecond)
			recMinute := recTime.Minute()

			tpt := tpr[0] //每X分钟
			tps := tpr[1] //消耗体力值

			difm := float64(recMinute) / float64(tpt)
			difm /= float64(tps)

			pot := s.Power - int32(difm)

			if cfgv.PowerRange != nil {
				min := cfgv.PowerRange[0]
				max := cfgv.PowerRange[1]
				tmpv := math.Max(float64(pot), float64(min)) //<=min取min
				tmpv = math.Min(tmpv, float64(max))          //>=max 取max
				pot = int32(tmpv)
			}
			bfpower := s.Power

			s.Power = pot
			fmt.Printf("Robot[sid:%v,cfgid:%v] PowerConsumeByTime ==> beforePower:%v time:%v afterPower:%v 每%v分钟消耗%v体力",
				s.Serid, s.Cfgid, bfpower, recTime, pot, tpt, tps)
		}
	}
}

// 机器人转入工作状态
func (s *Cache_buildrobot_info_robot_data) Trans2Work() {
	if !s.IsWork {
		s.IsWork = true
		s.LastWorkTime = time.Now().UnixMilli()
		if s.LastIdleTime > 0 { //如果最后空闲时间>0，则按空闲时间来恢复体力
			recTime := time.Now().UnixMilli() - s.LastIdleTime
			s.PowerRecoverByTime(recTime)
		}
		s.LastIdleTime = 0
	}
}

// 机器人转入空闲状态
func (s *Cache_buildrobot_info_robot_data) Trans2Idle() {
	if s.IsWork {
		s.IsWork = false
		s.LastIdleTime = time.Now().UnixMilli()
		if s.LastWorkTime > 0 { //如果最后工作的时间>0，则按工作时间来消耗体力
			recTime := time.Now().UnixMilli() - s.LastWorkTime
			s.PowerConsumeByTime(recTime)
		}
		s.LastWorkTime = 0
	}
}

// =======================数据库表【buildrobot_info】字段[build_data] =================================================================================
//
//	Cache_buildrobot_info_build_data
//
// [build_info_id_升级状态_机器人serids_升级前等级_升级后等级_升级开始时间戳_升级时间(秒)_升级结束时间戳_运输量_运输时间（秒）_总运输量_停止运输时时间间戳_停止时已运输量]
// =================================================================================================================================================
const (
	build_upgrade_none  int = iota //	未升级
	build_upgrade_uping            //	升级中
	build_upgrade_suc              //	升级成功
	build_upgrade_stop             //	停止升级
)

type Cache_buildrobot_info_build_data struct {
	Build_info_id      string  //建筑信息id
	enUpgradeState     int     //升级状态
	RobotSerids        []int32 //机器人服务器id组
	BeforeLv           int32   //升级前等级
	AfterLv            int32   //升级后等级
	StartMilliTime     int64   //开始时间戳
	UpgradeTime        int64   //升级时间（秒）
	EndMilliTime       int64   //结束时间戳
	TransVolume        int32   //运输量
	TransTimeSeconds   int32   //运输时间（秒）
	TotalTransVolume   int64   //总运输量
	StopTransMilliTime int64   //停止时已运输时间(毫秒)
	StopTransVolume    int64   //停止时已运输量

	Build_info_roleId      int64
	Build_info_mapId       int32
	Build_info_cfgBuildId  int32
	Build_info_svrConfigId int32
}

const (
	buildrobot_info_split_one = "_"
	buildrobot_info_split_two = ","
)

func (s *Cache_buildrobot_info_build_data) SetBuild_info_id(id string) {
	s.Build_info_id = id
	s.Build_info_roleId, s.Build_info_mapId, s.Build_info_cfgBuildId, s.Build_info_svrConfigId = build.SpitBuildKey(s.Build_info_id)
	s.BeforeLv, s.AfterLv = build.NextBuildLevel(s.Build_info_id)
}

func (s *Cache_buildrobot_info_build_data) SetValue(val string) {
	splitStr := strings.Split(val, buildrobot_info_split_one)
	if len(splitStr) > 0 {
		for i, sv := range splitStr {
			if i == 1 {
				s.SetValue_RobotSerids(sv)
			} else if v, err := strconv.Atoi(sv); err == nil {
				switch i {
				case 0:
					{
						s.enUpgradeState = v
					}
				case 2:
					{
						s.BeforeLv = int32(v)
					}
				case 3:
					{
						s.AfterLv = int32(v)
					}
				case 4:
					{
						s.StartMilliTime = int64(v)
					}
				case 5:
					{
						s.UpgradeTime = int64(v)
					}
				case 6:
					{
						s.EndMilliTime = int64(v)
					}
				case 7:
					{
						s.TransVolume = int32(v)
					}
				case 8:
					{
						s.TransTimeSeconds = int32(v)
					}
				case 9:
					{
						s.TotalTransVolume = int64(v)
					}
				case 10:
					{
						s.StopTransMilliTime = int64(v)
					}
				case 11:
					{
						s.StopTransVolume = int64(v)
					}
				}
			}
		}
	}
}

func (s *Cache_buildrobot_info_build_data) GetValue() string {

	combinStr := strings.Join([]string{
		strconv.FormatInt(int64(s.enUpgradeState), 10),
		s.GetValue_RobotSerids(),
		strconv.FormatInt(int64(s.BeforeLv), 10),
		strconv.FormatInt(int64(s.AfterLv), 10),
		strconv.FormatInt(s.StartMilliTime, 10),
		strconv.FormatInt(s.UpgradeTime, 10),
		strconv.FormatInt(s.EndMilliTime, 10),
		strconv.FormatInt(int64(s.TransVolume), 10),
		strconv.FormatInt(int64(s.TransTimeSeconds), 10),
		strconv.FormatInt(s.TotalTransVolume, 10),
		strconv.FormatInt(s.StopTransMilliTime, 10),
		strconv.FormatInt(s.StopTransVolume, 10),
	}, buildrobot_info_split_one)
	return combinStr
}

func (s *Cache_buildrobot_info_build_data) SetValue_RobotSerids(val string) {
	splitStr := strings.Split(val, buildrobot_info_split_two)
	s.RobotSerids = make([]int32, 0)
	if splitStr != nil {
		for i := 0; i < len(splitStr); i++ {
			if v, err := strconv.Atoi(splitStr[i]); err == nil {
				s.RobotSerids = append(s.RobotSerids, int32(v))
			}
		}
	}
}

func (s *Cache_buildrobot_info_build_data) GetValue_RobotSerids() string {
	combinStr := ""
	len := len(s.RobotSerids)
	if s.RobotSerids != nil && len > 0 {
		joins := make([]string, len)
		for i := 0; i < len; i++ {
			joins[i] = strconv.FormatInt(int64(s.RobotSerids[i]), 10)
		}
		combinStr = strings.Join(joins, buildrobot_info_split_two)
	}
	return combinStr
}

// 添加机器人
// 返回值：
// 参数一：[]int32 新添加的机器人ids
// 参数二：bool 是否有新加的机器人
func (s *Cache_buildrobot_info_build_data) AddRobot(rids []int32, funcGetRobotById func_buildrobot_info_GetRobotById) ([]int32, bool) {
	newAdd := util.NewSet[int32]()
	if rids != nil {
		usd := util.NewSet[int32]()
		usd.AddValue(s.RobotSerids)
		for i := 0; i < len(rids); i++ {
			tid := rids[i]
			if !usd.Contains(tid) {
				usd.Add(tid)
				newAdd.Add(tid)
				if r, ok := funcGetRobotById(tid); ok {
					r.Trans2Work()
				}
			}
		}
		s.RobotSerids = usd.Elements()
	}
	return newAdd.Elements(), newAdd.Size() > 0
}

// 添加机器人
// 返回值：
// 参数一：[]int32 移除的机器人ids
// 参数二：bool 是否有移除的机器人
func (s *Cache_buildrobot_info_build_data) RemoveRobot(rids []int32, funcGetRobotById func_buildrobot_info_GetRobotById) ([]int32, bool) {
	willremoves := util.NewSet[int32]()
	if rids != nil {
		usd := util.NewSet[int32]()
		usd.AddValue(s.RobotSerids)
		for i := 0; i < len(rids); i++ {
			tid := rids[i]
			if usd.Contains(tid) {
				usd.Remove(tid)
				willremoves.Add(tid)
				if r, ok := funcGetRobotById(tid); ok {
					r.Trans2Idle()
				}
			}
		}
		s.RobotSerids = usd.Elements()
	}
	return willremoves.Elements(), willremoves.Size() > 0
}

func (s *Cache_buildrobot_info_build_data) RemoveAllRobot(funcGetRobotById func_buildrobot_info_GetRobotById) bool {
	isModify := false
	rids := s.RobotSerids
	if rids != nil {
		for i := 0; i < len(rids); i++ {
			if rt, ok := funcGetRobotById(rids[i]); ok {
				rt.Trans2Idle()
				isModify = true
			}
		}
	}
	s.RobotSerids = nil
	return isModify
}

// 检测升级状态
// bool (true:升级成功,false:未成功)
func (s *Cache_buildrobot_info_build_data) CheckUpgradeState(
	funcGetRobotById func_buildrobot_info_GetRobotById, isUseAnyItem bool) bool {
	isUpgradeSuc := false
	nowMilliTime := time.Now().UnixMilli()

	isUpgradeSuc = (s.enUpgradeState == build_upgrade_uping || isUseAnyItem) && nowMilliTime >= s.EndMilliTime
	if isUpgradeSuc { //升级中并且升级成功的建筑
		s.RemoveAllRobot(funcGetRobotById)
		s.enUpgradeState = build_upgrade_suc
	}
	return isUpgradeSuc
}

// 获得机器人的状态系数
func (s *Cache_buildrobot_info_build_data) GetRobotWorkEfficiencyFactor(funcGetRobotById func_buildrobot_info_GetRobotById) float32 {
	rstFactor := float32(0)
	if s.RobotSerids != nil {
		for i := 0; i < len(s.RobotSerids); i++ {
			serid := s.RobotSerids[i]
			if rot, ok := funcGetRobotById(serid); ok {
				cfgVal := config_manager.GetTableRobotSheetRobot(rot.Cfgid)
				rss := cfgVal.RobotState
				maxts := int32(0) //机器人当前体力值最高状态
				if rss != nil {   //查找当前机器人状态
					for i := 0; i < len(rss); i++ {
						ts := rss[i].Value[0] //状态
						tp := rss[i].Value[1] //体力值
						if rot.Power <= tp {
							if maxts == 0 {
								maxts = ts
							} else {
								maxts = int32(math.Max(float64(ts), float64(maxts)))
							}
						}
					}
				}
				//根据当前体力值的最大状态获得工作效率
				rwt := cfgVal.RobotWork
				if rwt != nil {
					for i := 0; i < len(rwt); i++ {
						if rwt[i].Value[0] == maxts { //如果状态是最大状态
							rstFactor += float32(rwt[i].Value[1]) //工作效率
						}
					}
				}
			}
		}
		rstFactor /= float32(len(s.RobotSerids))
	}

	if math.IsNaN(float64(rstFactor)) {
		rstFactor = 0
	}
	return rstFactor
}

// 获得升级时间 total_consume:总消耗 spendtime:搬运时间 robotcnt:机器人数量
func (s *Cache_buildrobot_info_build_data) GetUpgradeMilliTime(total_consume int64, spendtime int32, robotcnt int32,
	transvolume int32, funcGetRobotById func_buildrobot_info_GetRobotById, totalTransVolume, stopTransVolume int64) int64 {
	factor := s.GetRobotWorkEfficiencyFactor(funcGetRobotById) //机器人状态系数
	if factor <= 0 {
		factor = 100
	}
	//升级时间 =>[资源需求总量/(工人单次运输量*工人数量）-0.5]*工人搬运时间 /（工人状态系数）
	seconds := (float64(total_consume)/float64(transvolume*robotcnt) - 0.5) * float64(spendtime) / float64(factor*0.01)
	zlog.Debugf("==========[资源需求总量%v/(工人单次运输量%v*工人数量%v）-0.5]*工人搬运时间%v /（工人状态系数%v）", total_consume, transvolume, robotcnt, spendtime, factor)

	time := int64(math.Round(seconds))

	/*	zlog.Debugf("GetUpgradeMilliTime=> [资源需求总量%v/(工人单次运输量%v*工人数量%v）-0.5]*工人搬运时间%v /（工人状态系数%v）---totalTransVolume:%v stopTransVolume:%v",
		total_consume, transvolume, robotcnt, spendtime, factor, totalTransVolume, stopTransVolume)*/

	if total_consume <= 0 {
		time = 0
	}
	return time * 1000
}

// 计算默认升级时间
func (s *Cache_buildrobot_info_build_data) CalculateDefaultUpgradeTime(transvolume int32, robotcnt int32, funcGetRobotById func_buildrobot_info_GetRobotById) {
	blvCfgTable := config_manager.GetTableBuildSheetLevelConfig(s.Build_info_cfgBuildId, s.AfterLv)
	itemsArray := make([][]int32, 0, len(blvCfgTable.Consume))

	for _, v := range blvCfgTable.Consume {
		//CheckItemEnough会区别是否是货币
		itemsArray = append(itemsArray, v.Value)
		s.TotalTransVolume += int64(v.Value[1])
	}
	//暂时升级只在资源够的情况下才可以升级
	//从仓库搬取=>[资源需求总量/(工人单次运输量*工人数量）-0.5]*工人从仓库到建筑物时间（读取bulid表）*（状态系数）
	s.TransTimeSeconds = blvCfgTable.SpendTime[0]
	/*if resEnough {
		//从仓库搬取=>[资源需求总量/(工人单次运输量*工人数量）-0.5]*工人从仓库到建筑物时间（读取bulid表）*（状态系数）
		s.TransTimeSeconds = blvCfgTable.SpendTime[0]
	} else {
		//从资源点获取=>•[资源需求总量/(工人单次运输量*工人数量）-0.5]*工人单次运输量/资源地每秒产量*工人从资源点到建筑物时间（读取bulid表）*（状态系数）
		s.TransTimeSeconds = blvCfgTable.SpendTime[1]
	}*/
	uplv_millitime := s.GetUpgradeMilliTime(s.TotalTransVolume, s.TransTimeSeconds, robotcnt, transvolume, funcGetRobotById, s.TotalTransVolume, s.StopTransVolume)
	s.StartMilliTime = time.Now().UnixMilli()
	s.EndMilliTime = s.StartMilliTime + uplv_millitime
	s.UpgradeTime = int64(float64(uplv_millitime) * 0.001)
}

// 计算升级时间 transvolume:运输量
func (s *Cache_buildrobot_info_build_data) CalculateUpgradeTime(transvolume int32, funcGetRobotById func_buildrobot_info_GetRobotById, onlyCalculate bool) bool {
	robotCount := int32(0)
	if s.RobotSerids != nil {
		robotCount = int32(len(s.RobotSerids))
	}

	willUpgrade := build_upgrade_none
	if robotCount > 0 {
		willUpgrade = build_upgrade_uping
	} else {
		willUpgrade = build_upgrade_stop
	}
	isChangUpgrade := s.enUpgradeState != willUpgrade
	s.enUpgradeState = willUpgrade

	isUpgradeOver := false
	switch s.enUpgradeState {
	case build_upgrade_uping: //如果升级中，则计算时间
		{
			//resEnough := true                                //资源是否足够
			total_transvolume := int64(0)                    //总运输量
			spendsecondstime := int32(0)                     //搬运时间
			if isChangUpgrade && s.StopTransMilliTime <= 0 { //由停止变为升级状态则需要重新计算时间
				s.CalculateDefaultUpgradeTime(transvolume, robotCount, funcGetRobotById)
				total_transvolume = s.TotalTransVolume
				//resEnough = bag.CheckArrayItemEnough(s.Build_info_roleId, itemsArray)
				s.StopTransMilliTime = 0
				s.StopTransVolume = 0
				if !onlyCalculate {
					go s.RegisterCountDownCheck_BuildRobotLvUpOver()
				}
			} else { //如果本来就在升级中，则:当前总运输量 =总运输量-已运输的量
				spendsecondstime = s.TransTimeSeconds
				total_transvolume = s.TotalTransVolume - s.StopTransVolume
				if total_transvolume > 0 && s.StopTransMilliTime > 0 {
					uplv_millitime := s.GetUpgradeMilliTime(total_transvolume, spendsecondstime, robotCount, transvolume, funcGetRobotById, s.TotalTransVolume, s.StopTransVolume)
					s.StartMilliTime = time.Now().UnixMilli()
					s.EndMilliTime = s.StartMilliTime + uplv_millitime
					s.UpgradeTime = int64(float64(uplv_millitime) * 0.001)
					s.StopTransMilliTime = 0
					s.StopTransVolume = 0
					if !onlyCalculate {
						go s.RegisterCountDownCheck_BuildRobotLvUpOver()
					}
				} else { //如查升级时间变了，则需要更新下结束时间
					ntm := time.Now().UnixMilli()
					edif := s.EndMilliTime - ntm
					pgs := float64(edif) / float64(s.EndMilliTime-s.StartMilliTime)
					ttt := int32(pgs * 100)
					pgs = float64(ttt) * 0.01

					tmpTotal_transvolume := total_transvolume
					total_transvolume = int64(float64(total_transvolume) * pgs)
					if total_transvolume <= 0 {
						total_transvolume = 0
					}

					zlog.Debugf("==========[开始时间 %v ，结束时间%v，当前时间%v，百分比 %v,总消耗 %v,百分比剩余 %v", s.StartMilliTime, s.EndMilliTime, ntm, pgs, tmpTotal_transvolume, total_transvolume)

					uplv_millitime := s.GetUpgradeMilliTime(total_transvolume, spendsecondstime, robotCount, transvolume, funcGetRobotById, s.TotalTransVolume, s.StopTransVolume)
					upgradetime := int64(float64(uplv_millitime) * 0.001)
					if upgradetime != s.UpgradeTime {
						s.EndMilliTime = s.StartMilliTime + uplv_millitime
						s.UpgradeTime = upgradetime
						if !onlyCalculate {
							go s.RegisterCountDownCheck_BuildRobotLvUpOver()
						}
					}
				}
			}
			total_transvolume = int64(math.Max(float64(0), float64(total_transvolume)))
			isUpgradeOver = total_transvolume <= 0 //在升级中，如果运输总量<= 0 则代表升级成功
			if isUpgradeOver {
				s.RemoveAllRobot(funcGetRobotById)
				s.enUpgradeState = build_upgrade_suc
			}
			s.TransVolume = transvolume
			s.TotalTransVolume = total_transvolume
		}
	case build_upgrade_suc: //如果升级成功，则什么都不做
		{

		}
	case build_upgrade_stop: //如果不在升级中
		{
			if isChangUpgrade { //由升级变为停止状态
				s.StopTransMilliTime = time.Now().UnixMilli() - s.StartMilliTime
				dift := s.EndMilliTime - s.StartMilliTime
				stt := float64(s.StopTransMilliTime) / float64(dift)
				stt = math.Max(0, stt)
				stt = math.Min(1, stt) //限定到0-1
				s.StopTransVolume = int64(float64(s.TotalTransVolume) * stt)

				spendsecondstime := s.TransTimeSeconds
				total_transvolume := s.TotalTransVolume - s.StopTransVolume
				//停止时，升级时间按一个机器人的运输量来算
				uplv_millitime := s.GetUpgradeMilliTime(total_transvolume, spendsecondstime, 1, transvolume, funcGetRobotById, s.TotalTransVolume, s.StopTransVolume)
				upgradetime := int64(float64(uplv_millitime) * 0.001)
				if upgradetime != s.UpgradeTime {
					s.EndMilliTime = s.StartMilliTime + uplv_millitime
					s.UpgradeTime = upgradetime
					go s.RegisterCountDownCheck_BuildRobotLvUpOver()
				}
			}
		}
	}
	return isUpgradeOver
}

// =================================================================================================================================================
//
// # Pb相关
//
// =================================================================================================================================================
func (s *Cache_buildrobot_info_build_data) ToPb_BuildRobotLvUpData(funcGetRobotById func_buildrobot_info_GetRobotById) *pb.BuildRobotLvUpData {
	//==升级中的建筑===============================================================================
	rstBuild := &pb.BuildRobotLvUpData{
		Buildmapid:   s.Build_info_mapId,
		Buildcfgid:   s.Build_info_cfgBuildId,
		Buildserid:   s.Build_info_svrConfigId,
		UpgradeState: pb.BuildRobotLvUpData_BuildUpgradeState(s.enUpgradeState),
	}

	//==建造中的机器人===============================================================================
	lvuprbs := make([]*pb.BuildRobotData, 0)
	if s.RobotSerids != nil {
		for i := 0; i < len(s.RobotSerids); i++ {
			if tr, ok := funcGetRobotById(s.RobotSerids[i]); ok {
				nr := &pb.BuildRobotData{
					Serid: tr.Serid,
					Cfgid: tr.Cfgid,
					Power: tr.Power,
				}
				lvuprbs = append(lvuprbs, nr)
			}
		}
	}

	if len(lvuprbs) > 0 {
		rstBuild.LvupRobotOneof = &pb.BuildRobotLvUpData_LvupRobot{
			LvupRobot: &pb.BuildRobotLvUpData_LvUpRobot{
				LvupRobots: lvuprbs,
			},
		}
	}

	//==升级时间===============================================================================
	if s.StartMilliTime > 0 && s.EndMilliTime > 0 && s.EndMilliTime >= s.StartMilliTime {
		switch s.enUpgradeState {
		case build_upgrade_suc:
			{
			}
		case build_upgrade_none:
			{
			}
		default:
			{
				rstBuild.LvupTimeOneof = &pb.BuildRobotLvUpData_LvupTime{
					LvupTime: &pb.BuildRobotLvUpData_LvUpTime{
						Starttime:        s.StartMilliTime,
						Endtime:          s.EndMilliTime,
						Stoptransvolume:  s.StopTransVolume,
						Totaltransvolume: s.TotalTransVolume,
					},
				}
			}
		}

	} else {
		zlog.Errorf("ToPb_BuildRobotLvUpData 结束时间小于开始时间=>StartMilliTime:%v , EndMilliTime:%V , enUpgradeState:%v", s.StartMilliTime, s.EndMilliTime, s.enUpgradeState)
	}
	return rstBuild
}

// =================================================================================================================================================
//
// # DB相关
//
// =================================================================================================================================================

func (s *Buildrobot_info_service) LoadByRoleId(roldid int64) *Cache_buildrobot_info {
	rst := &Cache_buildrobot_info{}
	if s.IsUseRedis {

	} else {
		db := dao.GetBuildRobotInfo(roldid)

		rst.RoleId = db.RoleId
		rst.MaxCount = db.MaxCount
		rst.TransVolume = db.TransVolume
		rst.SetRobotData(db.RobotData)
		rst.SetBuildData(db.BuildData)
		rst.BuildResourceData = db.BuildResourceData.Data()
	}
	return rst
}

// === Buildrobot_info_service SaveXXX =================================================================================

func (s *Cache_buildrobot_info) Save_AllBasic() {
	if Buildrobot_info_serviceObj.IsUseRedis {

	} else {

	}
	db := dao.GetBuildRobotInfo(s.RoleId)
	db.MaxCount = s.MaxCount
	db.TransVolume = s.TransVolume
	defer func() {
		dao.UpdateBasicBuildRobotInfo(db)
	}()
}

func (s *Cache_buildrobot_info) Save_AllData() {
	if Buildrobot_info_serviceObj.IsUseRedis {

	} else {

	}
	db := dao.GetBuildRobotInfo(s.RoleId)
	db.RobotData = s.GetRobotData()
	db.BuildData = s.GetBuildData()
	//defer func() {
		dao.UpdateDataBuildRobotInfo(db)
	//}()
}

func (s *Cache_buildrobot_info) Save_Robot() {
	if Buildrobot_info_serviceObj.IsUseRedis {

	} else {

	}
	db := dao.GetBuildRobotInfo(s.RoleId)
	db.MaxCount = s.MaxCount
	db.TransVolume = s.TransVolume
	db.RobotData = s.GetRobotData()
	defer func() {
		dao.UpdateRobotBuildRobotInfo(db)
	}()
}

func (s *Cache_buildrobot_info) Save_Only_RobotData() {
	if Buildrobot_info_serviceObj.IsUseRedis {

	} else {

	}
	db := dao.GetBuildRobotInfo(s.RoleId)
	db.RobotData = s.GetRobotData()
	defer func() {
		dao.UpdateBuildRobotInfo_Robot_Data(db)
	}()
}

func (s *Cache_buildrobot_info) Save_Only_BuildData() {
	if Buildrobot_info_serviceObj.IsUseRedis {

	} else {

	}
	db := dao.GetBuildRobotInfo(s.RoleId)
	db.BuildData = s.GetBuildData()
	defer func() {
		dao.UpdateBuildRobotInfo_Build_Data(db)
	}()
}

// 注册建筑升级倒计时检测Timer
func (s *Cache_buildrobot_info_build_data) RegisterCountDownCheck_BuildRobotLvUpOver() {
	go build.SetBuildLvupTime(s.Build_info_id, s.EndMilliTime)
	go Buildrobot_info_serviceObj.AddTimerCheck(s)
}
